# gozerbot/redispatcher.py
#
#

""" implement RE (regular expression) dispatcher """

__copyright__ = 'this file is in the public domain'

from gozerbot.generic import rlog, calledfrom, handle_exception
import gozerbot.thr as thr
import sys, re, copy, types

class Recallback(object):

    """ a regular expression callback """

    def __init__(self, index, regex, func, perm, plugname, speed, threaded):
        self.index = index
        self.regex = regex
        self.func = func
        if type(perm) == types.ListType:
            self.perms = list(perm)
        else:
            self.perms = [perm, ]
        self.plugname = plugname
        self.speed = copy.deepcopy(speed)
        self.threaded = copy.deepcopy(threaded)

class Redispatcher(list):

    """ this is were the regexs callbacks live """

    def __init__(self):
        list.__init__(self)

    def size(self):
        """ nr of callbacks """
        return len(self)

    def list(self, perm):
        """ list re with permission perm """
        result = []
        perm = perm.upper()
        for recom in self:
            if perm in recom.perms:
                result.append(recom)
        return result

    def permoverload(self, funcname, perm):
        """ overload permission of function with funcname  """
        perm = perm.upper()
        for recom in self:
            if recom.func.func_name == funcname:
                if perm not in recom.perms:
                    recom.perms.append(perm)
                return 1

    def add(self, index, regex, func, perm, speed=5, threaded=1):
        """ add a command """
        try:
            # get plugin name from where callback is added
            plugname = calledfrom(sys._getframe())
            # add Recallback
            self.append(Recallback(index, regex, func, perm, plugname, \
speed, threaded))
            self.sort(lambda a, b: cmp(a.index, b.index))
            rlog(-3, 'redispatcher', 'added %s (%s) ' % (regex, plugname))
        finally:
            pass


    def unload(self, plugname):
        """ unload regexs commands """
        got = 0
        try:
            for i in range(len(self)-1, -1 , -1):
                if self[i].plugname == plugname:
                    rlog(-3, 'redispatcher', 'unloading %s (%s)' % \
(self[i].regex, plugname))
                    del self[i]
                    got = 1
        finally:    
            pass
        if got:
            return 1

    def getcallback(self, txt):
        """ get re callback if txt matches """
        for i in self:
            try:
                result = re.search(i.regex, txt)
                if result:
                    return i
            except:
                pass

    def dispatch(self, callback, txt):
        """ dispatch callback on txt """
        try:
            result = re.search(callback.regex, txt)
            if callback.threaded:
                thr.start_new_thread(callback.func, (txt, result.groups()))
            else:
                callback.func(txt, result.groups())
                return 1
        except Exception, ex:
            handle_exception()

class Botredispatcher(Redispatcher):

    """ dispatcher on ircevent """

    def dispatch(self, callback, bot, ievent):
        """ dispatch callback on ircevent """
        try:
            result = re.search(callback.regex, ievent.txt)
            if result:
                
                ievent.usercmnd = 1
                rlog(10, 'redispatcher', '%s (%s) executing %s' % \
(ievent.nick, ievent.userhost, ievent.txt))
                if callback.threaded:
                    thr.start_bot_command(callback.func, (bot, ievent, \
result.groups()))
                else:
                    callback.func(bot, ievent, result.groups())
                return 1
        except Exception, ex:
            handle_exception(ievent)

rebefore = Botredispatcher()
reafter = Botredispatcher()
